#include "algo_volume.h"
#include "libvolume/MT_AreaCaculate.h"
#include "libvolume/MT_VolumeDetect_Logic.h"

#include <stdlib.h>
#include <stdio.h>

#include "Include/AuxLibs/Json/json.h"
#include "Include/AuxLibs/Json/value.h"
#include "Include/INetSdk.h" //  这个头文件包含了json格式取值的函数封装 如GetCgiJSValue_UInt。以后用cjson替代。

typedef Json::FastWriter CConfigWriter;
typedef Json::Reader CConfigReader;

#include "modbus-srv.h"
#include "algo_mgr.h"
#include "util.h"
#include "gige.h"
#include "sensor.h"

struct CalibrateParam* cp = NULL;
struct VolumDetectParam* vdp = NULL;

int _parse_web_param(struct VolumDetectParam* vdp, char* data, int channel)
{
    Json::Value table, ctable;
    CConfigReader JsonReader;
    if (JsonReader.parse(data, ctable) == false)
    {
        __log_mesg("parse volume web param error.\n");
        return 1;
    }
    table = ctable["AlarmCfg"][channel];
    
    vdp->BeltSuspend = false;
    GetCgiJSValue_Int(table,"Frequency", vdp->UpdatingTime);
    GetCgiJSValue_Int(table,"SampleCycle", vdp->InstantVolumeTime);
    GetCgiJSValue_Int(table,"LaserSens", vdp->Threshold);
    int out = 0;
    GetCgiJSValue_Int(table,"Output", out);
    vdp->OutputVolumFlag = out? true:false;
    GetCgiJSValue_Int(table,"Team1Hour", vdp->BanAddHour_1);
    GetCgiJSValue_Int(table,"Team1Minute", vdp->BanAddMinute_1);

    GetCgiJSValue_Int(table,"Team2Hour", vdp->BanAddHour_2);
    GetCgiJSValue_Int(table,"Team2Minute", vdp->BanAddMinute_2);

    vdp->BanAddHour_3 = -1;
    vdp->BanAddMinute_3 = -1;

    vdp->BanAddOpenFlag = 1;      // 是否开启班组累计值清零逻辑 0 不开 1 开启
	vdp->LoadingAddOpenFlag = 1;  // 装车累计值清零逻辑开启标志 0 不开 1 开启
	vdp->StopLoadingTime = 5;     // 停止装车后多久清零  minute  1-60
	vdp->AddZeroTriggerFlag = -1;  // 停车逻辑标志 0 不清零 1 清零

    double Beltspeed = 0;
    GetCgiJSValue_Double(table,"Beltspeed",Beltspeed);
    vdp->SpeedBelt = Beltspeed;

    double Bulkdensity = 0;
    GetCgiJSValue_Double(table,"Bulkdensity",Bulkdensity);
    vdp->Bulk_density = Bulkdensity;

    if (channel) {
        vdp->CamerFPS = gige_get_fps();
    } else {
        vdp->CamerFPS = sensor_get_fps();
    }

    return 0;
}

int _parse_calib_param(struct CalibrateParam* dst, char* data, int channel)
{
    CConfigReader JsonReader;
    Json::Value calibtable;
    if (JsonReader.parse(data,calibtable) == false) {
        __log_mesg("parse volume calib param error.\n");
        return 1;
    }
    
    GetCgiJSValue_Int(calibtable,"AreaEmptyBelt",dst->AreaEmptyBelt);
    GetCgiJSValue_Int(calibtable,"DiffAreaValue",dst->DiffAreaValue);

    if (channel) {
        dst->CamerFPS = gige_get_fps();
    } else {
        dst->CamerFPS = sensor_get_fps();
    }
    
    GetCgiJSValue_Int(calibtable,"InstallCamLaserDist",dst->InstallCamLaserDist);

    double dval = 0.f;
    GetCgiJSValue_Double(calibtable,"InstallCamPitch",dval);
    dst->InstallCamPitch = dval;

    GetCgiJSValue_Double(calibtable,"VerticalViewAngle",dval);
    dst->VerticalViewAngle = dval;

    GetCgiJSValue_Int(calibtable,"BandWidth",dst->BandWidth);
    GetCgiJSValue_Int(calibtable,"BandY",dst->BandY);
    GetCgiJSValue_Int(calibtable,"CamSetImgHeight",dst->CamSetImgHeight);
    GetCgiJSValue_Int(calibtable,"CamSetOffsetY",dst->CamSetOffsetY);
    GetCgiJSValue_Int(calibtable,"ImgHeight",dst->ImgHeight);
    GetCgiJSValue_Int(calibtable,"ImgWidth",dst->ImgWidth);

    GetCgiJSValue_Int(calibtable,"LaserLXP",dst->LaserLXP);
    GetCgiJSValue_Int(calibtable,"LaserRXP",dst->LaserRXP);
    GetCgiJSValue_Int(calibtable,"LaserYP",dst->LaserYP);
    GetCgiJSValue_Int(calibtable,"Threshold",dst->Threshold);
    GetCgiJSValue_Int(calibtable,"SampleCount",dst->SampleCount);

    GetCgiJSValue_Double(calibtable,"VanishPointX",dval);
    dst->VpX = dval;

    GetCgiJSValue_Double(calibtable,"VanishPointY",dval);
    dst->VpY = dval;

    GetCgiJSValue_Double(calibtable,"LaserWarningRate",dval);
    dst->LaserWarningRate = dval;
    return 0;
}

int _parse_param(struct CalibrateParam** pcp, struct VolumDetectParam** pvdp, char* paramfile, char* calibfile, int channel)
{
    char* data1 = NULL;
    char* data2 = NULL;
    *pcp = NULL;
    *pvdp = NULL;
    data1 = __read_file(paramfile);
    if (data1 == NULL) {
        __log_mesg("read %s error.\n", paramfile);
        goto error_end;
    }

    data2 = __read_file(calibfile);
    if (data2 == NULL) {
        __log_mesg("read %s error.\n", calibfile);
        goto error_end;
    }

    *pvdp = (struct VolumDetectParam*)malloc(sizeof(struct VolumDetectParam));
    if (*pvdp == NULL) {
        __log_mesg("malloc error.\n");
        goto error_end;
    }

    *pcp = (struct CalibrateParam*)malloc(sizeof(struct CalibrateParam));
    if (*pvdp == NULL) {
        __log_mesg("malloc error.\n");
        goto error_end;
    }

    if (_parse_web_param(*pvdp, data1, channel)) {
        __log_mesg("parse volume web param error.\n");
        goto error_end;
    }

    if (_parse_calib_param(*pcp, data2, channel)) {
        __log_mesg("parse volume calib param error.\n");
        goto error_end;
    }

    free(data1);
    free(data2);
    return 0;
error_end:
    if (data1) free(data1);
    if (data2) free(data2);
    if (*pcp) {free(*pcp); *pcp = NULL;}
    if (*pvdp) {free(*pvdp); *pvdp = NULL;}
}

int init_volume(void* arg)
{
    algo_info* algo = (algo_info*)arg;
    char paramfile[256];
    sprintf(paramfile, "%s/%s", MTPath, algo->name);
    char calibfile[256] = {"/mnt/meiteng/VolumeDetect_711.json"};
    if (_parse_param(&cp, &vdp, paramfile, calibfile, algo->channel)) {
        return 1;
    }

    MT_VolumeDetect_ImgProInit(cp);
    ParamInit(vdp);

    return 0;
}

void* compute_volume(void* algo, unsigned char* data, int width, int height)
{
    unsigned char laserError = 0;
    float farea = MT_VolumeDetect_Compute(data, laserError);
    AlgoOutput_VolumeDetect res;
    OutPutVolume(farea, &res);
    
    set_input_register_uint16(laserError, TIE_VOLUME_DEVICE_ADDR);
    set_input_register_uint16(vdp->OutputVolumFlag, TIE_VOLUME_METRIC_ADDR); 

    if (res.Value_flag) {
        set_input_register_float_dcba(res.VolumeOfInstant, TIE_VOLUME_INSTANT_ADDR);
        set_input_register_float_dcba(res.VolumeOfBanAdd, TIE_VOLUME_BAN_ACC_ADDR);
        set_input_register_float_dcba(res.VolumeOfAdd, TIE_VOLUME_ALL_ACC_ADDR);
        __log_mesg("laserError=%d, instant = %.2f acc1 = %.2f acc2 = %.2f\n", laserError, res.VolumeOfInstant, res.VolumeOfBanAdd, res.VolumeOfAdd);
    }
    return NULL; 
}

void* analysis_volume(void* input)
{ 
    __log_mesg("Run analysis_volume. Must error.\n");
}

void debug_volume(unsigned char* data, int width, int height)
{
    printf("vol: debug\n");
}

int response_volume(void* algo, void* input) {
    __log_mesg("Run response_volume. Must error.\n");
}

void destroy_volume(void* arg)
{
    if (cp) {free(cp); cp = NULL;}
    if (vdp) {free(vdp); vdp = NULL;}
}